import projectSetting from "@/settings/project";
import useUserStore from "@/store/user";
import useAppStore from "@/store/app";
import * as Icons from "@ant-design/icons-vue";
import type {App} from "vue";
import district from "@/utils/city";
import mitt from "mitt";
import {customRef} from "vue";
import {huaWeiDoCreateObject, obsUploadApi} from "@/api/common";

export const authKey = "qwer-token";

export function registeIcon(app: App): void {
  // 注册图标组件
  for (let i in Icons) {
    app.component(i, Icons[i]);
  }
}

/**
 * 防抖ref
 * @param value
 * @param delay
 */
export function useDebouncedRef(value, delay = 200) {
  let timeout;
  return customRef((track, trigger) => {
    return {
      get() {
        track();
        return value;
      },
      set(newValue) {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
          value = newValue;
          trigger();
        }, delay);
      }
    };
  });
}
/**
 * 获取上传的objectKey
 * @param handle 当前所操作的vue文件名
 * @param fileName 文件的名字 例如test.png
 */
export const getObjectKey = (handle: string, fileName: string) => {
  let name = fileName.substring(0, fileName.lastIndexOf("."));
  let typeName = fileName.substring(fileName.lastIndexOf("."));
  let objectKey = `${handle}/${name}${algorithm()}${typeName}`;
  return objectKey;
};
/**
 * 获取随机字符串
 */
export const algorithm = () => {
  let abc = [
    "a",
    "b",
    "c",
    "d",
    "e",
    "f",
    "g",
    "h",
    "i",
    "g",
    "k",
    "l",
    "m",
    "n",
    "o",
    "p",
    "q",
    "r",
    "s",
    "t",
    "u",
    "v",
    "w",
    "x",
    "y",
    "z"
  ];
  let [max, min] = [
    Math.floor(Math.random() * (10 - 7 + 1) + 1),
    Math.floor(Math.random() * (17 - 10 + 1) + 17)
  ];
  let str = abc
    .sort(() => 0.4 - Math.random())
    .slice(max, min)
    .slice(0, 8)
    .join("");
  let res = new Date().getTime() + str;
  return res;
};
/**
 * 应用初始化操作
 */
export const appinit = () => {
  //初始化操作
  if (!getToken()) {
    return false;
  }
  // 加载字典列表
  useAppStore.loadDicList();
};

export function registeMitt(app: App): void {
  // 注册mitt组件
  let emitter = mitt();
  app.config.globalProperties.$emitter = emitter;
}

const modules = import.meta.glob("@/**/*.vue");

/**
 * 根据后台返回的路径，生成页面的组件模版
 * @param component 组件路径
 */
export const loadView = (component: string) => {
  return modules["/src/" + component + ".vue"];
};

export const makeRoutes = async (routes: object[]) => {
  routes.forEach((item: any) => {
    item.component = loadView(item.component);
    item.meta.hiddenChildren = item.isHiddenChildren;
    item.meta.hidden = item.isHidden;
    if (item.children && item.children.length) {
      makeRoutes(item.children);
    }
  });
  return routes;
};

/**
 * 获取两个日期中所有的月份
 * 参数示例 （'2021-01-01','2021-06-01'）
 * @param start 开始时间
 * @param end 结束时间
 */
export const getMonthBetween = (start, end) => {
  let result: any = [];
  let min = new Date(start);
  let max = new Date(end);
  let curr = min;
  do {
    let month = new Date(curr).getMonth() + 1;
    let t: any;
    if (month < 10) {
      t = "0" + month;
    } else t = month;
    let str = curr.getFullYear() + "-" + t;
    result.push(str);
    if (month == 12) {
      curr.setFullYear(new Date(curr).getFullYear() + 1);
      curr.setMonth(0);
    } else curr.setMonth(month);
  } while (curr <= max);
  return result;
};

/**
 * 深拷贝
 * @param param
 */
export const deepClone = (param: any) => {
  return JSON.parse(JSON.stringify(param));
};

/**
 * 防抖
 * @param fn
 * @param time 间隔时间
 */
export const debounce = function (fn: Function, time: number) {
  let timer;
  return function (...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(null, args);
    }, time);
  };
};

/**
 * 节流
 * @param fn
 * @param time 间隔时间
 */
export const throttle = (fn, delay) => {
  let valid = true;
  return function (...args) {
    if (valid) {
      setTimeout(() => {
        fn.apply(null, args);
        valid = true;
      }, delay);
      valid = false;
    }
  };
};

/**
 * 获取路由title
 * @param pageTitle
 */
export const getTitle = (pageTitle?: string) => {
  let title = projectSetting.projectTitle || "后台管理模板";
  if (pageTitle) {
    return `${pageTitle} - ${title}`;
  }
  return `${title}`;
};

/**
 * 获取登录信息
 */
export const getAuthInfo = () => {
  let authInfo: any = localStorage.getItem(authKey);
  return JSON.parse(authInfo);
};

/**
 * 获取token
 */
export const getToken = () => {
  let authInfo: any = localStorage.getItem(authKey);
  let token;
  if (authInfo) {
    token = JSON.parse(authInfo).token;
  }
  return token;
};

/**
 * 设置登录信息
 */
export const setAuthInfo = (authInfo) => {
  localStorage.setItem(authKey, JSON.stringify(authInfo));
};

/**
 * 移除登录信息 权限 路由
 */
export const removeAuthInfo = () => {
  localStorage.clear();
  useUserStore.userInfo = {};
  useUserStore.authMenus = [];
};

export const noBug = () => {
  console.log(
    "                   _oo0oo_                                         \n" +
      "                  o8888888o										\n" +
      '                  88" . "88										\n' +
      "                  (| -_- |)										\n" +
      "                   O\\ = /O										\n" +
      "               ____/`---'\\____									\n" +
      "             .   ' \\\\| |// `.									\n" +
      "              / \\\\||| : |||// \\								    \n" +
      "           / _||||| -卍- |||||- \\								    \n" +
      "              | | \\\\\\ - /// | |								    \n" +
      "            | \\_| ''\\---/'' | |								    \n" +
      "             \\ .-\\__ `-` ___/-. /							    \n" +
      "          ___`. .' /--.--\\ `. . __							    \n" +
      '       ."" "< `.___\\_<|>_/___. ` >" "".                           \n' +
      "      | | : `- \\`.;`\\ _ /`;.`/ - ` : | |                         \n" +
      "        \\ \\ `-. \\_ __\\ /__ _/ .-` / /                          \n" +
      "======`-.____`-.___\\_____/___.-`____.-'======                     \n" +
      "                   `=---='                                         \n" +
      ".............................................                      \n\t\t" +
      "佛祖镇楼                  BUG辟易                                    \n\t" +
      "佛曰:\n\t\t" +
      "写字楼里写字间，写字间里程序员；\n\t\t" +
      "程序人员写程序，又拿程序换酒钱。\n\t\t" +
      "酒醒只在网上坐，酒醉还来网下眠；\n\t\t" +
      "酒醉酒醒日复日，网上网下年复年。\n\t\t" +
      "但愿老死电脑间，不愿鞠躬老板前；\n\t\t" +
      "奔驰宝马贵者趣，公交自行程序员。\n\t\t" +
      "别人笑我忒疯癫，我笑自己命太贱；\n\t\t" +
      "不见满街漂亮妹，哪个归得程序员？"
  );
};

/**
 * 获取本月为止之前的月份列表
 * @param length
 */
export const getMonths = (isCurYear = true) => {
  let arr: object[] = [];
  let month = 0;
  if (isCurYear) {
    month = new Date().getMonth() + 1;
  } else {
    month = 12;
  }
  for (let i = 1; i <= month; i++) {
    let obj = {
      id: Math.random(),
      value: i < 10 ? "0" + i : i,
      name: i < 10 ? "0" + i + "月" : i + "月"
    };
    arr.push(obj);
  }
  return arr.reverse();
};

/**
 * 格式化金额 千分位&&保留两位小数
 * @param num 金额
 * @param needZero 当数量为0时是否返回0.00
 * @param isDecimal 是否返回保留小数
 */
export const formatMoney = (num, needZero = false, isDecimal = true) => {
  if (
    num === null ||
    num === undefined ||
    num === "" ||
    num === "0" ||
    num === 0 ||
    (typeof num === "number" && isNaN(num))
  ) {
    if (isDecimal) {
      if (needZero) {
        return "0.00";
      } else {
        return "";
      }
    } else {
      return "0";
    }
  }
  if (isDecimal) {
    let source = Number(num).toFixed(2).split("."); //按小数点分成2部分
    source[0] = source[0].replace(
      new RegExp("(\\d)(?=(\\d{3})+$)", "ig"),
      "$1,"
    ); //只将整数部分进行都好分割
    return source.join("."); //再将小数部分合并进来
  } else {
    num = num.replace(new RegExp("(\\d)(?=(\\d{3})+$)", "ig"), "$1,"); //只将整数部分进行都好分割
    return num;
  }
};

/**
 * 模拟上传点击
 */
export const trigerUpload = () => {
  return new Promise((resolve) => {
    let input = document.createElement("input");
    input.setAttribute("type", "file");
    input.style.display = "none";
    document.body.appendChild(input);
    input.click();
    input.addEventListener("change", (e) => {
      resolve(e);
      document.body.removeChild(input);
    });
  });
};
/**
 * 上传到Obs
 */
export const trigerUploadObs = (fileInfo) => {
  return new Promise((resolve, reject) => {
    let file = fileInfo.target.files[0];
    let objectKey = getObjectKey("dongcheng/file", file.name);
    huaWeiDoCreateObject({
      objectKey: objectKey,
      contextType: file.type
    }).then((res) => {
      obsUploadApi(
        file,
        res.data.data.signUrl,
        res.data.data.actualSignedRequestHeaders
      )
        .then(() => {
          let url =
            "https://kacunchu001.obs.cn-east-3.myhuaweicloud.com/" + objectKey;
          resolve(url);
        })
        .catch(() => {
          reject();
        });
    });
  });
};
/**
 * 模拟上传点击 多文件上传
 */
export const trigerUploadMuch = (): Promise<any> => {
  return new Promise((resolve) => {
    let input = document.createElement("input");
    input.setAttribute("type", "file");
    input.setAttribute("multiple", "true");
    input.style.display = "none";
    document.body.appendChild(input);
    input.click();
    input.addEventListener("change", (e) => {
      resolve(e);
      document.body.removeChild(input);
    });
  });
};
/**
 * 多文件上传
 */
export async function uploadMuchUrl(arr = []) {
  let urlList: any = [];
  let details: any = [];
  for (let index = 0; index < arr.length; index++) {
    let files: any = arr[index];
    try {
      let data: any = await trigerUploadObsMuch(files);
      urlList.push(data);
      details.push({fileName: files.name, fileUrl: data});
    } catch {
      return;
    }
  }
  return {urlList, details};
}
/**
 * 上传到Obs多上传
 */
export async function trigerUploadObsMuch(fileInfo) {
  let objectKey = getObjectKey("dongcheng/file", fileInfo.name);
  let a = await huaWeiDoCreateObject({
    objectKey: objectKey,
    contextType: fileInfo.type
  });
  await obsUploadApi(
    fileInfo,
    a.data.data.signUrl,
    a.data.data.actualSignedRequestHeaders
  );
  return "https://kacunchu001.obs.cn-east-3.myhuaweicloud.com/" + objectKey;
}
/**
 * 生成指定长度的随机字符串
 * @param length 字符串长度
 */
export const randomString = (length: number = 16): string => {
  const characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let result = "";
  const charactersLength = characters.length;
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
};

/**
 * 获取字典值
 * @param key 字典唯一标识
 */
export const getDicValue = (key: string | number): any[] => {
  let arr = JSON.parse(localStorage.getItem("dicList") || "[]");
  if (!arr.length) return [];
  let curItem = arr.find((item, index) => {
    return item.code == key;
  });
  if (curItem) return curItem.children;
  return [];
};
/**
 * Table 列的值 把编码改为对应的名称
 * @param list （包括字典和自定义的列表数据）
 * @param code 编码
 * @returns 对应的名称
 */
export const getCodeName = (list: object[], code: string | number) => {
  if (list.length == 0 || (!code && code != 0)) return;
  // 过滤数组
  let filterList: any = list.filter((item: any) => {
    return item.code == code || item.value == code;
  });
  // 取值
  let name = "";
  if (filterList.length != 0) {
    name = filterList[0].name || filterList[0].label || filterList[0].title;
  } else {
    name = "";
  }

  return name;
};
/**
 * 获取字典值
 * @param key 字典唯一标识
 * @param value 字典某一项的值
 */
export const getDicLabel = (
  key: string | number,
  value: string | number
): string | number => {
  let arr = JSON.parse(localStorage.getItem("dicList") || "[]");
  if (!arr.length) return "";
  let curItem = arr.find((item, index) => {
    return item.code == key;
  });
  if (!curItem || !curItem.children.length) return "";
  let item = curItem.children.find((item, index) => {
    return item.dictValue == value;
  });
  if (!item) return "";
  return item.dictLabel;
};
//下拉框搜索方法
export const filterOption = (input: string, option: any) => {
  return option.title.toLowerCase().indexOf(input.toLowerCase()) >= 0;
};
/**
 * 导出
 * @param data blob对象
 * @param fileName 文件名
 * @param isXlsx 是否是表格
 */
export const exportData = (
  data,
  fileName: string = "file",
  isXlsx: Boolean = true
) => {
  var blobURL = window.URL.createObjectURL(data);
  var tempLink = document.createElement("a");
  tempLink.style.display = "none";
  tempLink.href = blobURL;
  if (isXlsx) {
    tempLink.setAttribute("download", `${fileName}.xls`);
  } else {
    tempLink.setAttribute("download", fileName);
  }
  if (typeof tempLink.download === "undefined") {
    tempLink.setAttribute("target", "_blank");
  }
  document.body.appendChild(tempLink);
  tempLink.click();
  document.body.removeChild(tempLink); // 移除dom元素
  window.URL.revokeObjectURL(blobURL); // 释放bolb内存
};
/**
 * 加减法精度计算  保留六位小数
 * @param num1 数字1
 * @param num2 数字2
 * @param method  add 加 subtract 减 multiply 乘 divide 除
 */
export function arithmetic(num1, num2, method) {
  if (isNaN(num1)) {
    num1 = 0;
  }
  if (isNaN(num2)) {
    num2 = 0;
  }
  num1 = Number(num1);
  num2 = Number(num2);
  var r1, r2, m, n;
  try {
    r1 = num1.toString().split(".")[1].length;
  } catch (e) {
    r1 = 0;
  }
  try {
    r2 = num2.toString().split(".")[1].length;
  } catch (e) {
    r2 = 0;
  }
  m = Math.pow(10, Math.max(r1, r2));
  // n = (r1 >= r2) ? r1 : r2;
  if (method === "add") {
    return Number(((num1 * m + num2 * m) / m).toFixed(6));
  } else if (method === "subtract") {
    return Number(((num1 * m - num2 * m) / m).toFixed(6));
  } else if (method === "multiply") {
    return Number(((num1 * m * num2 * m) / Math.pow(m, 2)).toFixed(6));
  } else if (method === "divide") {
    return Number(((num1 * m) / (num2 * m)).toFixed(6));
  }
}
/**
 * 截取字符串
 * @param str 类似于11+2*3/(4-5)的字符串 返回["11","+","2","*","3","/","(","4","-","5",")"]
 */
export function extractNumbersAndOperators(str) {
  const regex = /(\d+|[+\-*/()])/g;
  const result: any = [];
  let match;
  while ((match = regex.exec(str)) !== null) {
    result.push(match[1]);
  }
  return result;
}
/**
 * 计算
 * @param strList 类似于["1","+","2"] 的集合
 */
export function calculateStrList(strList) {
  //优先计算括号包裹的内容
}
/**
 * 处理地区数据结构
 *  district 地区数据
 * @returns filterList 过滤后地区数据->目前是根据<a-cascader/>组件数据结构过滤的
 */
export const getAddressList = () => {
  let filterList = district.map((item) => {
    return {
      label: item.name,
      value: item.code,
      level: "1",
      children:
        item.children.map((item1) => {
          return {
            label: item1.name,
            value: item1.code,
            level: "2",
            children:
              item1.children.map((item2) => {
                return {
                  label: item2.name,
                  value: item2.code,
                  level: "3"
                };
              }) || []
          };
        }) || []
    };
  });
  return filterList;
};
/**
 * 解决表格使用复选框有分页使用 onChange 回调函数第二个参数选中数据详情中存在undefined 的情况
 * @param oldData 老数据
 * @param newData 新数据
 * @param ids  当前已选中的ID集合
 * @returns 返回的是完整的已选中数据的详情集合
 */
export const ComputedReturnValue = (
  oldData: Array<object> = [],
  newData: Array<object> = [],
  ids: Array<String> = []
) => {
  let newList: any = [];
  let oldList: any = JSON.parse(JSON.stringify(oldData));
  newData.forEach((item: any) => {
    if (item) {
      let sameData = oldData.find((v: any) => {
        return v.id == item.id;
      });
      if (sameData == undefined) {
        oldList.push(item);
      }
    }
  });
  oldList.forEach((item) => {
    if (ids.includes(item.id)) {
      newList.push(item);
    }
  });
  return newList;
};
export enum EnumAlias {
  PROJECT = "dongcheng",
  MODULE_AUTH = "auth",
  MODULE_SYS = "sys",
  MODULE_MALL = "mall",
  MODULE_WEB = "web",
  MODULE_WORKFLOW = "workflow"
}
